package com.wutma.common.service;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicSessionCredentials;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.region.Region;
import com.wutma.common.core.constants.CacheConstants;
import com.wutma.common.core.constants.Constants;
import com.wutma.common.core.enums.ResultCode;
import com.wutma.common.core.utils.ThreadLocalUtil;
import com.wutma.common.redis.service.RedisService;
import com.wutma.common.security.exception.ServiceException;
import com.wutma.common.domain.COSResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.wutma.common.util.ConstantPropertiesUtil;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@RefreshScope
public class COSService {

    @Autowired
    private RedisService redisService;

    @Value("${file.max-time}")
    private int maxTime;

    @Value("${file.test}")
    private boolean test;

    public COSResult uploadFile(MultipartFile file){
        if (!test) {
            checkUploadCount();
        }
        // 1 传入获取到的临时密钥 (tmpSecretId, tmpSecretKey, sessionToken)
        String tmpSecretId = ConstantPropertiesUtil.ACCESS_KEY_ID;
        String tmpSecretKey = ConstantPropertiesUtil.ACCESS_KEY_SECRET;
        String bucketName = ConstantPropertiesUtil.BUCKET_NAME;
        String endpoint = ConstantPropertiesUtil.END_POINT;
        String sessionToken = Constants.COS_TOKEN;
        BasicSessionCredentials cred = new BasicSessionCredentials(tmpSecretId, tmpSecretKey, sessionToken);
        // 2 设置 bucket 的地域
        // clientConfig 中包含了设置 region, https(默认 http),
        // 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分
        Region region = new Region(endpoint); //COS_REGION 参数：配置成存储桶 bucket 的实际地域，例如 ap-beijing，更多 COS 地域的简称请参见 https://cloud.tencent.com/document/product/436/6224
        ClientConfig clientConfig = new ClientConfig(region);
        // 3 生成 cos 客户端
        COSClient cosClient = new COSClient(cred, clientConfig);
        try{
            // 指定要上传的文件
            InputStream inputStream = file.getInputStream();
            // 指定文件将要存放的存储桶
            // 指定文件上传到 COS 上的路径，即对象键。例如对象键为folder/picture.jpg，则表示将文件 picture.jpg 上传到 folder 路径下
            //上传同名的文件，后面会覆盖掉前面的，需要添加uuid让文件名不重复，并且为了美观可以将-去掉
            String key = UUID.randomUUID().toString().replaceAll("-","")+
                    file.getOriginalFilename();
            //对文件可以进行分组处理，比如当前2023/4/2，通过刚刚添加的依赖

            key = ConstantPropertiesUtil.FOLDER_NAME + "/" + key;
            ObjectMetadata objectMetadata = new ObjectMetadata();

            PutObjectRequest putObjectRequest =new PutObjectRequest
                    (bucketName, key, inputStream,objectMetadata);

            PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
//            System.out.println(JSON.toString(putObjectResult));
            //返回上传文件的路径
            //https://yu-1317492111.cos.ap-beijing.myqcloud.com/2.jpg
            String url = "https://"+bucketName+"."+"cos"+"."+endpoint+".myqcloud.com"+"/"+key;
            return assembleCOSResult(url, putObjectResult);
        } catch (Exception clientException) {
            throw new ServiceException(ResultCode.FAILED_FILE_UPLOAD);
        }
    }

    private void checkUploadCount() {
        // 限定当天用户上传图片次数
        Long userId = ThreadLocalUtil.get(Constants.USER_ID, Long.class);
        Long times = redisService.getCacheMapValue(CacheConstants.USER_UPLOAD_TIMES_KEY, String.valueOf(userId), Long.class);
        if (times != null && times >= maxTime) {
            throw new ServiceException(ResultCode.FAILED_FILE_UPLOAD_TIME_LIMIT);
        }
        redisService.incrementHashValue(CacheConstants.USER_UPLOAD_TIMES_KEY, String.valueOf(userId), 1);
        if (times == null || times == 0) {
            long seconds = ChronoUnit.SECONDS.between(LocalDateTime.now(),
                    LocalDateTime.now().plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0));
            redisService.expire(CacheConstants.USER_UPLOAD_TIMES_KEY, seconds, TimeUnit.SECONDS);
        }
    }


    private COSResult assembleCOSResult(String key, PutObjectResult putObjectResult) {
        COSResult ossResult = new COSResult();
        if (putObjectResult == null || StrUtil.isBlank(putObjectResult.getRequestId())) {
            ossResult.setSuccess(false);
        } else {
            ossResult.setSuccess(true);
            ossResult.setName(key);
        }
        return ossResult;
    }
}
